<?php

namespace common\observer;

use common\model\EntityModel;
use common\model\TaskMemberModel;
use common\model\TaskRelationModel;
use common\service\StatusService;
use common\service\TaskAssembleService;
use support\SingletonTrait;
use teamones\dbeventObserver\interfaces\SplObserver;
use teamones\dbeventObserver\interfaces\SplSubject;
use think\Hook;

/**
 * 标准任务完成 通知下游文件更新
 */
class TaskDoneNotifyRelateTask implements SplObserver
{
    use SingletonTrait;

    /**
     * @inheritDoc
     */
    function update(SplSubject $subject): void
    {
        $updateData = $subject->getSplUpdateData();
        if (!isset($updateData['task_status'])) {
            return;
        }
        $task = $subject->getSubjectData();
        if (in_array($task['step_type'], ['step_category', 'step'])) {
            return;
        }
        if ($updateData['task_status'] != StatusService::getInstance()->getTaskDoneStatus()['id']) {
            return;
        }

        $relateTaskList = model(TaskRelationModel::class)
            ->setSuffix(sprintf('_project_%d', $task['project_id'] ?? 0))
            ->alias('task_relation')
            ->join('task on task.id = task_relation.source_task_id')
            ->where([
                'task_relation.target_task_id' => $task['id'],
                'task.json->>"$.task_status"' => ['in', StatusService::getInstance()->byCodeMap(['closed, not_started'], true, 'id')],
                'relation_type' => 'upstream',
            ])
            ->field('task.*')
            ->group('task.id')
            ->select();

        if (empty($relateTaskList)) {
            return;
        }
        $relatePartner = model(TaskMemberModel::class)
            ->where([
                'task_id' => ['in', array_column($relateTaskList, 'id')]
            ])
            ->field('task_id, partner')
            ->select();
        $relatePartnerMap = array_group_by($relatePartner, 'task_id');

        $relateEntity = model(EntityModel::class)
            ->where([
                'id' => ['in', array_column($relateTaskList, 'entity_id')],
            ])
            ->select();
        $relateEntityMap = array_column($relateEntity, null, 'id');

        $taskName = TaskAssembleService::getInstance()->getNotifyTaskName($relateEntityMap[$task['entity_id']] ?? [], $task);
        foreach ($relateTaskList as $relateTask) {
            $hookData = [
                'type' => 'task_finish_informing_downstream',
                'data' => [
                    'task' => $relateTask,
                    'entity' => $relateEntityMap[$relateTask['id']] ?? [],
                    'current_task_name' => $taskName,
                    'partner' => array_unique(array_column($relatePartnerMap[$relateTask['id']] ?? [], 'partner')),
                ]
            ];
            Hook::listen('task_done_with_file_after', $hookData);
        }
    }
}
